package com.company.jrlz.service.opcua.config;

import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.api.identity.AnonymousProvider;
import org.eclipse.milo.opcua.sdk.client.api.identity.IdentityProvider;
import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
import org.eclipse.milo.opcua.stack.core.types.builtin.LocalizedText;
import org.eclipse.milo.opcua.stack.core.types.structured.EndpointDescription;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.function.Predicate;

import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;

/**
 * Created by ziye on 2023/9/6
 */
public class AutoReconnectUaClientFactory implements OpcUaClientFactory {

    private String uaAddress;

    // EndpointDescription 端点描述
    private Predicate<EndpointDescription> endpointFilter = e -> true;
    // Predicate接口主要用来判断一个参数是否符合要求
    // Predicate 从类文件生成的 IntelliJ API Decompiler 存根源

    // 安全政策
    private SecurityPolicy securityPolicy = SecurityPolicy.None;

    // 身份提供者 ：这里 Anonymous 匿名
    private IdentityProvider identityProvider = new AnonymousProvider();


    @Override
    public OpcUaClient createUaClient() throws Exception {
        OpcUaClient opcUaClient;

        Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "security");
        Files.createDirectories(securityTempDir);
        if (!Files.exists(securityTempDir)) {
            throw new Exception("unable to create security dir: " + securityTempDir);
        }

        KeyStoreLoader loader = new KeyStoreLoader().load(securityTempDir);

        opcUaClient = OpcUaClient.create(
                uaAddress,
                endpoints ->
                        endpoints.stream()
                                .filter(endpointFilter())
                                .findFirst(),
                configBuilder ->
                        configBuilder
                                .setApplicationName(LocalizedText.english("eclipse milo opc-ua client"))
                                .setApplicationUri("urn:eclipse:milo:examples:client")
                                .setCertificate(loader.getClientCertificate())
                                .setKeyPair(loader.getClientKeyPair())
                                .setIdentityProvider(identityProvider)
                                .setRequestTimeout(uint(8000))
                                .build()
        );

        Thread.sleep(3000);

        return opcUaClient;


    }

    private Predicate<EndpointDescription> endpointFilter() {
        return e -> securityPolicy.getUri().equals(e.getSecurityPolicyUri());
    }

    @Override
    public String getUaAddress() {
        return uaAddress;
    }

    public void setUaAddress(String uaAddress) {
        this.uaAddress = uaAddress;
    }
}
